package rursu.dal.loaders;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import rursu.business.ProgressListener;
import rursu.business.Settings;
import rursu.business.pojo.Movie;
import rursu.business.pojo.MovieImage;
import rursu.business.pojo.MoviesList;
import rursu.dal.managers.DataBaseManager;
import rursu.dal.managers.interfaces.IMovieDAL;

import rursu.dal.managers.interfaces.IMovieDetailsDAL;
import rursu.dal.managers.interfaces.IMovieImageDAL;
import rursu.dal.managers.interfaces.IMovieSearchDAL;
import rursu.dal.managers.interfaces.IMoviesListDAL;
import rursu.dal.managers.interfaces.IMoviesListPairDAL;
import rursu.parser.MoviesListParser;
import rursu.parser.MoviesListSAXParser;
import rursu.providers.MoviesListCallback;
import android.os.AsyncTask;


public class SearchMoviesLoaderTask extends AsyncTask<Void, Void, List<Movie>> {	 

	private static final String SEARCH_LIST_TYPE_NAME = "search";
	
	private DataBaseManager dataBaseManager;
	private IMovieDAL movieDALManager;
	private IMoviesListDAL moviesListDALManager;
	private IMoviesListPairDAL moviesListPairDALManager;
	private IMovieImageDAL movieImageDALManager;
	private IMovieDetailsDAL movieDetailsDAL;
	private IMovieSearchDAL movieSearchDALManager;
	private MoviesListCallback callback;
	private ProgressListener progressListener;
	private Settings settings;
	private String url;
	private String query;
	
	private final int LIST_VALID_PERIOD = 3*1000*60*60*24; // milliseconds
	
	public SearchMoviesLoaderTask(MoviesListCallback callback) {
		this.callback = callback;
	}
	
	public ProgressListener getProgressListener() {
		return progressListener;
	}

	public void setProgressListener(ProgressListener progressListener) {
		this.progressListener = progressListener;
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		
		if ( progressListener != null ) {
			progressListener.progressContinue();
		}
	}
	
	@Override
	protected void onCancelled() {
		if (progressListener != null) {
			progressListener.progressFinished();
		}
	}
	
	@Override
	protected List<Movie> doInBackground(Void... links) {
		
		List<Movie> movies = null;
		
		movieDALManager 			= dataBaseManager.getMovieDALManager();
		moviesListDALManager 		= dataBaseManager.getMoviesListDALManager();
		moviesListPairDALManager 	= dataBaseManager.getMoviesListPairDALManager();
		movieImageDALManager 		= dataBaseManager.getMovieImageDALManager();
		movieDetailsDAL 			= dataBaseManager.getMovieDetailsDALManager();
		movieSearchDALManager 		= dataBaseManager.getMovieSearchDALManager();
		
		MoviesList movieList 		= moviesListDALManager.get(SEARCH_LIST_TYPE_NAME);
		
		int oldListId = -1;
		
		if (movieList != null) {
			
			oldListId = movieList.getId();
			
			long currentTime = (new Date()).getTime();
			long recordAge = currentTime - movieList.getDateOfRecord().getTime();
			
			String lastQuery = movieSearchDALManager.getQuery();
				
			if (recordAge < LIST_VALID_PERIOD && lastQuery != null && query.equals(lastQuery)) {
				return movieDALManager.getMoviesByListId(movieList.getId());
			} else {
				
				List<Movie> oldMovies = movieDALManager.getMoviesByListId(oldListId);
				List<Movie> moviesToDelete = new ArrayList<Movie>();
				
				if (oldMovies != null) {
					
					for (Movie movie : oldMovies) {
						
						int listsNum = moviesListPairDALManager.getMoviesListIds(movie.getId()).size();
						
						if (listsNum <= 1) {
							moviesToDelete.add(movie);
						}
					}
					
					moviesListDALManager.delete(oldListId);
					movieSearchDALManager.delete(lastQuery);
					moviesListPairDALManager.deleteMoviesList(oldListId);
				
					for (Movie movie : moviesToDelete) {
						movieDALManager.delete(movie.getId());						
						movieImageDALManager.deleteByMovieId(movie.getId());
						movieDetailsDAL.delete(movie.getId());
					}
					
				}
			}
		}
			
		// load new movies from network
		movies = downloadMovies();
		
		// save movies in DB
		movieList = new MoviesList();
		movieList.setDateOfRecord(new Date());
		movieList.setOrderBy(SEARCH_LIST_TYPE_NAME);
		moviesListDALManager.insert(movieList);
		movieSearchDALManager.insert(query);
		movieList = moviesListDALManager.get(SEARCH_LIST_TYPE_NAME);
		
		int listId = movieList.getId();
		
		for (Movie movie : movies ) {
			moviesListPairDALManager.insert(movie.getId(), listId);
			
			if (movieDALManager.get(movie.getId()) == null) {
				movieDALManager.insert(movie);
			}			
			
			for (MovieImage image : movie.getImages()) {
				
				if (image.getSize().equals("thumb") && image.getType().equals("poster")) {
					
					movieImageDALManager.insert(image, movie.getId(), null);
					
				}
			}
		}
		
		return movies;
	}

	@Override
	protected void onPostExecute(List<Movie> result) {
		callback.onDownloaded(result);
		
		
		if (progressListener != null) {
			progressListener.progressFinished();
		}
	}
	
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public DataBaseManager getDataBaseManager() {
		return dataBaseManager;
	}

	public void setDataBaseManager(DataBaseManager dataBaseManager) {
		this.dataBaseManager = dataBaseManager;
	}
	
	private List<Movie> downloadMovies() {
		MoviesListParser parser = new MoviesListSAXParser();	
		URL url;
		InputStream inputStream = null;
			
		try {
			url = new URL( this.url );
			inputStream = url.openStream();
			
		} catch (MalformedURLException e) {
				
			e.printStackTrace();
		} catch (IOException e) {
				
			e.printStackTrace();
		}
			
		return parser.parse( inputStream );
	}

	public Settings getSettings() {
		return settings;
	}

	public void setSettings(Settings settings) {
		this.settings = settings;
	}

	public String getQuery() {
		return query;
	}

	public void setQuery(String query) {
		this.query = query;
	}	
	
	
	
}
